{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Labeling: Fixed Horizon\n",
    "\n",
    "![image_example](img/fixed_horizon_labels_example.png)\n",
    "_*Fig. 1:*_ Distribution of labels for standardized returns on closing prices of SPY in the time period from Jan 2008 to July 2016 using a 20-day rolling window for the standard deviation.\n",
    "\n",
    "\n",
    "## Abstract\n",
    "\n",
    "Fixed Horizon is a classification labeling technique in which time-indexed data is labeled according to whether it exceeds, falls in between, or is less than a threshold. This method is most commonly used with time bars, but also be applied to any time-indexed data such as dollar or volume bars. The subsequent labeled data can then be used as training and test data for ML algorithms.\n",
    "\n",
    "The following paper outlines the technique in greater depth, and is followed closely in this notebook tutorial: [\"Classification-based Financial Markets Prediction using Deep Neural Networks\"](https://arxiv.org/abs/1603.08604) by _Dixon et al._ (2016). \n",
    "\n",
    "\n",
    "## How it works\n",
    "\n",
    "Fixed time horizon is a common method used in labeling financial data, usually applied on time bars. The return relative to $t_0$ over a time horizon $h$ is calculated as follows, assuming returns are lagged to make them forward-looking:\n",
    "\n",
    "   $$r_{t0,t1} = \\frac{p_{t1}}{p_{t0}} - 1$$\n",
    "\n",
    "Where $t_1$ is the time bar after a fixed horizon has passed, and $p_{t0}, p_{t1}$\n",
    "are prices at times $t_0, t_1$. This method assigns a label based on comparison of return to a threshold $\\tau$\n",
    "\\[Lopez de Prado 2018\\]:\n",
    "\n",
    "$$\n",
    "     \\begin{equation}\n",
    "     \\begin{split}\n",
    "       L_{t0, t1} = \\begin{cases}\n",
    "       -1 &\\ \\text{if} \\ \\ r_{t0, t1} < -\\tau\\\\\n",
    "       0 &\\ \\text{if} \\ \\ -\\tau \\leq r_{t0, t1} \\leq \\tau\\\\\n",
    "       1 &\\ \\text{if} \\ \\ r_{t0, t1} > \\tau\n",
    "       \\end{cases}\n",
    "     \\end{split}\n",
    "     \\end{equation}\n",
    "$$\n",
    "\n",
    "To avoid overlapping return windows, rather than specifying $h$, the user is given the option of resampling the returns to get the desired return period. Optionally, returns can be standardized by scaling by the mean and standard deviation of a rolling window. If threshold is a pd.Series, **threshold.index and prices.index must match**; otherwise labels will fail to be returned. If resampling is used, the threshold must match the index of prices after resampling. This is to avoid the user being forced to manually fill in thresholds. Acceptable strings inputs for resampling can be found [here](https://pandas.pydata.org/pandas-docs/stable/user_guide/timeseries.html#dateoffset-objects).\n",
    "\n",
    "Though time bars are the most common format for financial data, there can be potential problems with over-reliance on time bars. Time bars exhibit high seasonality, as trading behavior may be quite different at the open or close versus midday; thus it will not be informative to apply the same threshold on a non-uniform distribution. Solutions include applying the fixed horizon method to tick or volume bars instead of time bars, using data sampled at the same time every day (e.g. closing prices) or inputting a dynamic threshold as a pd.Series corresponding to the timestamps in the dataset. However, the fixed horizon method will always fail to capture information about the path of the prices [Lopez de Prado, 2018].\n",
    "\n",
    "---\n",
    "## Examples of use"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import pandas as pd\n",
    "import yfinance as yf\n",
    "\n",
    "from mlfinlab.labeling import fixed_time_horizon\n",
    "\n",
    "import matplotlib.pyplot as plt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Date\n",
       "2010-01-04    24.23\n",
       "2010-01-05    24.23\n",
       "2010-01-06    24.09\n",
       "2010-01-07    23.84\n",
       "2010-01-08    24.00\n",
       "Name: Close, dtype: float64"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Load price data. pd.Series is shown but pd.DataFrame works as well.\n",
    "msft = yf.Ticker('MSFT')\n",
    "msft_df = msft.history(start='2010-1-1', end ='2020-5-18')\n",
    "\n",
    "close = msft_df['Close']\n",
    "close.head()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Labeling financial time series"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Getting labels for a constant threshold of 1%. Will return 1 if the daily return is greater than 1%,\n",
    "# -1 if less than -1%, and  0 if in between.\n",
    "bars1 = fixed_time_horizon(prices=close, threshold=0.01, lag=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Text(0, 0.5, 'Frequency')"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "ax1 = bars1.value_counts().reindex([-1, 0, 1]).plot(kind='bar', x='label', y='frequency')\n",
    "ax1.set_xlabel('Label')\n",
    "ax1.set_ylabel('Frequency')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Predictably, lowering the threshold results in fewer 0 labels."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Text(0, 0.5, 'Frequency')"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "bars2 = fixed_time_horizon(prices=close, threshold=0.001, lag=True)\n",
    "ax2 = bars2.value_counts().reindex([-1, 0, 1]).plot(kind='bar', x='label', y='frequency')\n",
    "ax2.set_xlabel('Label')\n",
    "ax2.set_ylabel('Frequency')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Labeling with dynamic threshold"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "A major problem with the fixed time horizon method is the seasonality of the data. Time bars in the middle of the trading day would look very different than those at the open or close. One way to get around this is to only use data which has been collected at the same time per day, such as close prices. Another method is to apply a dynamic threshold which can adjust for such differences. \n",
    "\n",
    "We will demonstrate two methods of setting a dynamic threshold:\n",
    "1. Using a rolling standard deviation.\n",
    "2. Using SPY as the market return.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Rolling standard deviation\n",
    "msft_returns = close.pct_change(periods=1).shift(-1)\n",
    "rolling_std = msft_returns.rolling(10).std()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Because the first 9 values in the rolling_std are NaN due to the rolling window, there is no threshold to compare the first 9 returns to. So we must remove the first 9 returns as they are not labeled."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "bars3 = fixed_time_horizon(prices=close, threshold=rolling_std, lag=True)\n",
    "bars3 = bars3.iloc[9:]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Text(0, 0.5, 'Frequency')"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "ax3 = bars3.value_counts().reindex([-1, 0, 1]).plot(kind='bar', x='label', y='frequency')\n",
    "ax3.set_xlabel('Label')\n",
    "ax3.set_ylabel('Frequency')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Date\n",
       "2010-01-04    0.002602\n",
       "2010-01-05    0.000757\n",
       "2010-01-06    0.004213\n",
       "2010-01-07    0.003335\n",
       "2010-01-08    0.001394\n",
       "Name: Close, dtype: float64"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Threshold on market returns\n",
    "spy = yf.Ticker('SPY')\n",
    "spy_df = spy.history(start='2010-1-1', end ='2020-5-18')\n",
    "market_close = spy_df['Close']\n",
    "\n",
    "market_returns = market_close.pct_change(1).shift(-1)\n",
    "market_returns.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "bars4 = fixed_time_horizon(prices=close, threshold=market_returns, lag=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Text(0, 0.5, 'Frequency')"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "ax4 = bars4.value_counts().reindex([-1, 0, 1]).plot(kind='bar', x='label', y='frequency')\n",
    "ax4.set_xlabel('Label')\n",
    "ax4.set_ylabel('Frequency')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "These 2 methods of setting a dynamic threshold accomplish slightly different things. By setting the threshold equal to the rolling standard deviation, we can see if the day's volatility is higher than in recent days. By setting the threshold equal to the return on SPY, we can see if our stock's return was more volatile than the market average for the day."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Labeling with standardization "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Scaling each return by the mean and standard deviation is also a potential solution in getting around the non-homogeneity of the data, as it could adjust for volatility differences between different bars. If standardization is desired, a rolling window must be given."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Date\n",
       "2010-01-04    0.000000\n",
       "2010-01-05   -0.005778\n",
       "2010-01-06   -0.010378\n",
       "2010-01-07    0.006711\n",
       "2010-01-08   -0.012917\n",
       "                ...   \n",
       "2020-05-11   -0.022661\n",
       "2020-05-12   -0.015110\n",
       "2020-05-13    0.004351\n",
       "2020-05-14    0.014553\n",
       "2020-05-15         NaN\n",
       "Name: Close, Length: 2610, dtype: float64"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "close.pct_change(periods=1).shift(-1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "bars5 = fixed_time_horizon(prices=close, threshold=1, lag=True, standardized=True, window=5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Text(0, 0.5, 'Frequency')"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "ax5 = bars5.value_counts().reindex([-1, 0, 1]).plot(kind='bar', x='label', y='frequency')\n",
    "ax5.set_xlabel('Label')\n",
    "ax5.set_ylabel('Frequency')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Labeling with resampling"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Sometimes the data is more granular then necessary. Suppose we only want to predict returns on a weekly timescale but have daily data. Then we can resample the prices weekly so that only the price at the end of each week gets sampled. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [],
   "source": [
    "bars6 = fixed_time_horizon(prices=close, threshold=1, resample_by='W', lag=True, standardized=True, window=4)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Text(0, 0.5, 'Frequency')"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "ax6 = bars6.value_counts().reindex([-1, 0, 1]).plot(kind='bar', x='label', y='frequency')\n",
    "ax6.set_xlabel('Label')\n",
    "ax6.set_ylabel('Frequency')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Error Handling"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "A warning is raised if window is greater than the length of the data. In this case, the function will still run, but all labels will be NaN. An exception is raised if standardized is set to True but the window is not specified correctly as an int. An exception is also raised if the index of threshold does not match the index of prices, as this will cause the labeling to fail."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "c:\\users\\ruifan\\mlfinlab\\mlfinlab\\labeling\\fixed_time_horizon.py:61: UserWarning: window is greater than the length of the Series. All labels will be NaN.\n",
      "  warnings.warn('window is greater than the length of the Series. All labels will be NaN.', UserWarning)\n"
     ]
    }
   ],
   "source": [
    "try:\n",
    "    fixed_time_horizon(close, 0.01, standardized=True, window=9999999).head()\n",
    "except Warning as warn:\n",
    "    print(warn)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "prices.index and threshold.index must match! If prices are resampled, the threshold index must match the resampled prices index.\n"
     ]
    }
   ],
   "source": [
    "threshold = pd.Series([0.01]*10)\n",
    "try:\n",
    "    fixed_time_horizon(prices=close[:10], threshold=threshold)\n",
    "except Exception as exc:\n",
    "    print(exc)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "When standardized is True, window must be int.\n"
     ]
    }
   ],
   "source": [
    "try:\n",
    "    fixed_time_horizon(prices=close, threshold=0.01, lag=True, standardized=True, window='str')\n",
    "except Exception as exc:\n",
    "    print(exc)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "## Conclusion"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This notebook presents the fixed horizon method, a simple method of labeling data for later use in machine learning algorithms. In this process:\n",
    " - Forward (lagged) returns for assets are calculated based on time-indexed data, usually in the form of time bars. If applicable, the returns may be calculated from resampled prices.\n",
    " - The forward return is compared to a threshold for the return. The threshold can be a constant, or a pd.Series corresponding to every timestamp in the data.\n",
    " - Each observation is compared to the threshold, and is labeled -1 if it is below -threshold, 0 if it is between -threshold and +threshold, and 1 if it is greater than +threshold.to\n",
    "\n",
    "This method works with the prices input being pd.Series or pd.DataFrame. In Dixon's paper, the data is labeled using this method. Subsequently a neural network is trained to predict the label based on the data. A simple trading strategy in which a long position is taken if a ticker is classified as 1, and short if it's classified at -1, can then be applied. "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## References"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "1. Dixon, M., Klabjan, D. and Jin Hoon, B., 2020. Classification-based Financial Markets Prediction using Deep Neural Networks. arXiv, [online] Available at: https://arxiv.org/abs/1603.08604\n",
    "\n",
    "2. López de Prado, M., 2018. Advances In Financial Machine Learning. pp.43-44.\n",
    "\n",
    "3. López de Prado, M., 2020. Machine Learning For Asset Managers. pp.65-66.\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
